package com.sk.bilibili.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sk.bilibili.bean.*;
import com.sk.bilibili.dto.DynamicInfo;
import com.sk.bilibili.event.BiliBiliEvent;
import com.sk.bilibili.other.R;
import com.sk.bilibili.utils.BSessionUtils;
import com.sk.bilibili.utils.QueryWrapperUtils;
import com.sk.bilibili.utils.WarpUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import com.sk.bilibili.mapper.DynamicMapper;

import java.util.ArrayList;
import java.util.List;

/**
 * @author 邵康
 * @date 2021/11/24 11:44
 */
@Service
public class DynamicService extends ServiceImpl<DynamicMapper, Dynamic> {

    @Autowired
    private FocusService focusService;
    @Autowired
    private MemberService memberService;
    @Autowired
    private WarpUtils warpUtils;
    @Autowired
    private FollowThemService followThemService;
    @Autowired
    private MemberExtendService memberExtendService;
    @Autowired
    private TypeService typeService;
    @Autowired
    private ThemService themService;
    @Autowired
    private ApplicationEventPublisher eventPublisher;

    public R<Void> add(Dynamic dynamic) {
        save(dynamic);
        return R.success();
    }

    public R<Void> delete(Integer id) {
        Dynamic dynamic = getById(id);
        if(dynamic.getType()<2)return R.error("只有转发动态,图文动态可以删除");
        eventPublisher.publishEvent(new BiliBiliEvent<>(this,dynamic));
        removeById(id);
        return R.success();
    }

    public R<Void> update(Dynamic dynamic) {
        updateById(dynamic);
        return R.success();
    }

    public R<IPage<Dynamic>> page(Integer page, Integer size) {
        return R.success(page(new Page<>(page, size), null));
    }

    public R<IPage<Dynamic>> getHotDynamic(Integer page, Integer size) {
        QueryWrapper<Dynamic> queryWrapper = QueryWrapperUtils.ne("type", 1);
        return getPageRes(page, size, queryWrapper);
    }

    private R<IPage<Dynamic>> getPageRes(Integer page, Integer size, QueryWrapper<Dynamic> queryWrapper) {
        queryWrapper.orderByDesc("create_date");
        IPage<Dynamic> dynamicPage = page(new Page<>(page, size), queryWrapper);
        int memberId = BSessionUtils.getMemberId();
        dynamicPage.getRecords().forEach(dynamic -> warpDynamic(dynamic, memberId));
        return R.success(dynamicPage);
    }

    public R<IPage<Dynamic>> getMemberDynamic(DynamicInfo dynamicInfo) {
        if(dynamicInfo.getMemberId()==null)dynamicInfo.setMemberId(BSessionUtils.getMemberId());
        QueryWrapper<Dynamic> queryWrapper = QueryWrapperUtils.eq("member_id", dynamicInfo.getMemberId());
        MemberExtend memberExtend = memberExtendService.getById(dynamicInfo.getMemberId());
        queryWrapper.ne("id",memberExtend.getTopDynamicId());
        return getPageRes(dynamicInfo.getPage(), dynamicInfo.getSize(), queryWrapper);
    }

    public R<IPage<Dynamic>> getDynamic(DynamicInfo dynamicInfo) {
        int memberId = BSessionUtils.getMemberId();
        List<Integer> focusIds = getFocusId(memberId);
        List<Integer> themIds = followThemService.getFollowThemId(memberId);
        IPage<Dynamic> dynamicPage = handleType(dynamicInfo, focusIds, themIds);
        dynamicPage.getRecords().forEach(dynamic -> warpDynamic(dynamic, memberId));
        return R.success(dynamicPage);
    }


    public R<IPage<Dynamic>> pageSearch(DynamicInfo dynamicInfo) {
        int memberId = BSessionUtils.getMemberId();
        QueryWrapper<Dynamic> queryWrapper = new QueryWrapper<>();
        queryWrapper.like("title",dynamicInfo.getKeyword());
        IPage<Dynamic> page = page(dynamicInfo.page(), queryWrapper);
        page.getRecords().forEach(dynamic -> warpDynamic(dynamic,memberId));
        eventPublisher.publishEvent(new BiliBiliEvent<>(this,dynamicInfo));
        return R.success(page);
    }

    private IPage<Dynamic> handleType(DynamicInfo dynamicInfo, List<Integer> focusIds, List<Integer> themIds) {
        Page<Dynamic> page = dynamicInfo.page();
        if (dynamicInfo.getType() == null) {//手动使用sql解决
            return baseMapper.getDynamic(page, focusIds, themIds);
        } else {
            QueryWrapper<Dynamic> queryWrapper = QueryWrapperUtils.eq("type", dynamicInfo.getType());
            queryWrapper.orderByDesc("create_date");
            switch (dynamicInfo.getType()) {
                case 0:// 只看关注人的视频
                    queryWrapper.in("member_id", focusIds);
                    return page(page, queryWrapper);
                case 1:// 看追番更新
                    if(themIds.isEmpty())return new Page<>();//  若为条件为null  就不再查询数据库了  否则该条件会去掉变为查询所有
                    queryWrapper.in("target_id", themIds);
                    return page(page, queryWrapper);
                default:
                    throw new RuntimeException("还不支持该类型:"+dynamicInfo.getType());
            }
        }
    }

    private List<Integer> getFocusId(Integer memberId) {
        List<Integer> ids = new ArrayList<>();
        ids.add(memberId);//获取自己的动态
        ids.addAll(focusService.getAllFocus(memberId));
        return ids;
    }

    public void warpDynamic(Dynamic dynamic, int memberId) {
        Member member = memberService.getById(dynamic.getMemberId());
        memberService.warpFocus(memberId, member);
        dynamic.getExtra().addExtra(member);
        dynamic.getExtra().addExtra(warpUtils.getTypeTarget(dynamic.getType(), dynamic.getTargetId()));
    }

    /**
     * 添加动态
     */
    public void save(int type, Integer targetId, int memberId,String title) {
        Dynamic dynamic = new Dynamic();
        dynamic.setType(type);
        dynamic.setTargetId(targetId);
        dynamic.setMemberId(memberId);
        dynamic.setTitle(title);
        save(dynamic);
        eventPublisher.publishEvent(new BiliBiliEvent<>(this,dynamic));
    }

    public Integer getDynamicNum(Integer id) {
        QueryWrapper<Dynamic> queryWrapper = QueryWrapperUtils.eq("member_id", id);
        return count(queryWrapper);
    }

    @EventListener(condition = "event.type == 'com.sk.bilibili.service.ForwardService.add'")
    public void handleForwardAdd(BiliBiliEvent<Forward> event){
        Forward forward = event.getData();
        save(5,forward.getId(), forward.getMemberId(),forward.getContent());
    }

    @EventListener(condition = "event.type == 'com.sk.bilibili.service.NoteService.add'")
    public void handleNoteAdd(BiliBiliEvent<Note> event){
        Note note = event.getData();
        save(2,note.getId(),note.getMemberId(),note.getContent());
    }

    @EventListener(condition = "event.type == 'com.sk.bilibili.service.VideoService.add'")
    public void handleVideoAdd(BiliBiliEvent<Video> event){
        Video video = event.getData();
        if (!typeService.isThem(video.getVideoSetId())) return;
        Integer themId = themService.getThemId(video.getVideoSetId());
        if (themId == null) return;//可能还没有升为番剧
        save(1, themId, BSessionUtils.getMemberId(),video.getTitle());
    }

    @EventListener(condition = "event.type == 'com.sk.bilibili.service.VideoService.add'")
    public void handleVideoSetAdd(BiliBiliEvent<VideoSet> event){
        VideoSet videoSet = event.getData();
        save(0,videoSet.getId(),videoSet.getMemberId(),videoSet.getTitle());
    }

//    public Dynamic getDynamic(Integer type, Integer targetId) {
//        if(type!=8)return null;//若不是对动态处理 直接  返回null
//        return getById(targetId);
//    }

}
